﻿Namespace Extensions
    Public Class PasswordBoxExtension

        Public Shared ReadOnly PasswordProperty As DependencyProperty = _
            DependencyProperty.RegisterAttached("Password", _
                                                GetType(String), GetType(PasswordBoxExtension), _
                                                New FrameworkPropertyMetadata(String.Empty, AddressOf OnPasswordPropertyChanged))

        Public Shared ReadOnly AttachProperty As DependencyProperty = _
            DependencyProperty.RegisterAttached("Attach", _
                                                GetType(Boolean), _
                                                GetType(PasswordBoxExtension), _
                                                New PropertyMetadata(False, AddressOf Attach))

        Private Shared ReadOnly IsUpdatingProperty As DependencyProperty = _
            DependencyProperty.RegisterAttached("IsUpdating", GetType(Boolean), GetType(PasswordBoxExtension))

        Public Shared Sub SetAttach(ByVal dp As DependencyObject, ByVal value As Boolean)
            dp.SetValue(AttachProperty, value)
        End Sub

        Public Shared Function GetAttach(ByVal dp As DependencyObject) As Boolean
            Return CBool(dp.GetValue(AttachProperty))
        End Function

        Public Shared Function GetPassword(ByVal dp As DependencyObject) As String
            Return DirectCast(dp.GetValue(PasswordProperty), String)
        End Function

        Public Shared Sub SetPassword(ByVal dp As DependencyObject, ByVal value As String)
            dp.SetValue(PasswordProperty, value)
        End Sub

        Private Shared Function GetIsUpdating(ByVal dp As DependencyObject) As Boolean
            Return CBool(dp.GetValue(IsUpdatingProperty))
        End Function

        Private Shared Sub SetIsUpdating(ByVal dp As DependencyObject, ByVal value As Boolean)
            dp.SetValue(IsUpdatingProperty, value)
        End Sub

        Private Shared Sub OnPasswordPropertyChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
            Dim passwordBox As PasswordBox = TryCast(sender, PasswordBox)
            RemoveHandler passwordBox.PasswordChanged, AddressOf PasswordChanged

            If Not CBool(GetIsUpdating(passwordBox)) Then
                passwordBox.Password = DirectCast(e.NewValue, String)
            End If

            AddHandler passwordBox.PasswordChanged, AddressOf PasswordChanged
        End Sub

        Private Shared Sub Attach(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
            Dim passwordBox As PasswordBox = TryCast(sender, PasswordBox)

            If passwordBox Is Nothing Then
                Return
            End If

            If CBool(e.OldValue) Then
                RemoveHandler passwordBox.PasswordChanged, AddressOf PasswordChanged
            End If

            If CBool(e.NewValue) Then
                AddHandler passwordBox.PasswordChanged, AddressOf PasswordChanged
            End If
        End Sub

        Private Shared Sub PasswordChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim passwordBox As PasswordBox = TryCast(sender, PasswordBox)
            SetIsUpdating(passwordBox, True)
            SetPassword(passwordBox, passwordBox.Password)
            SetIsUpdating(passwordBox, False)
        End Sub
    End Class
End Namespace
